package conbtract

import (
	"bytes"
	"context"
	"fmt"
	"github.com/ethereum/go-ethereum"
	_ "github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
	"log"
	"math/big"
	"os"
	"path/filepath"
	"runtime"
)

const contract_address = "0x8fADa6dF0836B780C1a6bF221A33287cB29e2aD4"

const eth_rpc = "http://8.153.91.50:8545"

func Execute(name string, args ...interface{}) {
	client, contractAbi, _ := getClient()

	contractAddress := common.HexToAddress(contract_address)
	var pack = new([]byte)
	if args == nil {
		i, err := contractAbi.Pack(name)
		pack = &i
		if err != nil {
			log.Fatal("Error packing args", err)
		}
	} else {
		i, err := contractAbi.Pack(name, args...)
		pack = &i
		if err != nil {
			log.Fatal("Error packing args", err)
		}
	}

	privateKey, _ := crypto.HexToECDSA("f31ff46311447e5553dda9da89bb4bc50565c10b4d846ff49f50c9e4b47c0b09")
	// 3️⃣ 获取账户地址
	fromAddress := crypto.PubkeyToAddress(privateKey.PublicKey)
	fmt.Println("使用账户:", fromAddress.Hex())

	nonce, _ := client.PendingNonceAt(context.Background(), fromAddress)
	price, _ := client.SuggestGasPrice(context.Background())

	tx := types.NewTransaction(
		nonce, contractAddress, big.NewInt(0), uint64(300000), price, *pack,
	)
	chainID, _ := client.NetworkID(context.Background())
	signTx, _ := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)
	err := client.SendTransaction(context.Background(), signTx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Transaction sent hash %s", signTx.Hash().Hex())
}

func getClient() (client *ethclient.Client, abiJson *abi.ABI, err error) {
	_, filename, _, _ := runtime.Caller(0) // 获取当前文件路径
	dir := filepath.Dir(filename)
	abiPath := filepath.Join(dir, "config.abi") // 拼接文件路径// 当前文件所在目录
	file, err := os.ReadFile(abiPath)
	if err != nil {
		log.Fatal(err)
	}
	contractApi, err := abi.JSON(bytes.NewReader(file))
	if err != nil {
		log.Fatal(err)
	}

	client, err = ethclient.Dial(eth_rpc)
	defer client.Close()

	return client, &contractApi, err
}

func GetValue(name string, args ...interface{}) {
	client, contractAbi, _ := getClient()
	// 0xC8939fF63BB164D1Bff73fabd5aBae2DE04FbF8e
	contractAddress := common.HexToAddress(contract_address)
	var pack = new([]byte)
	if args == nil {
		i, err := contractAbi.Pack(name)
		pack = &i
		if err != nil {
			log.Fatal("Error packing args", err)
		}
	} else {
		i, err := contractAbi.Pack(name, args...)
		pack = &i
		if err != nil {
			log.Fatal("Error packing args", err)
		}
	}

	msg := ethereum.CallMsg{
		To:   &contractAddress,
		Data: *pack,
	}

	res, err := client.CallContract(context.Background(), msg, nil)
	if err != nil {
		log.Fatal(err)
	}
	log.Println(res)

	var result interface{}
	err = contractAbi.UnpackIntoInterface(&result, name, res)
	if err != nil {
		log.Fatalf("Failed to unpack result: %v", err)
	}

	fmt.Println("Contract getValue:", result)
}

func C_test() {

}

func SetValue(num int) {

}

//if err != nil {
//log.Fatal(err)
//}
//msg := ethereum.CallMsg{
//To:   &address,
//Data: *pack,
//}
//
//res, err := client.CallContract(context.Background(), msg, nil)
//if err != nil {
//log.Fatal(err)
//}
//
//var result *big.Int
//err = contractApi.UnpackIntoInterface(&result, name, res)
//if err != nil {
//log.Fatalf("Failed to unpack result: %v", err)
//}
//
//fmt.Println("Contract getValue:", result)
